package com.zhn.evsi.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhn.evsi.client.MarketClient;
import com.zhn.evsi.client.ThirdClient;
import com.zhn.evsi.common.RedisCache;
import com.zhn.evsi.domain.dto.evsi.EvsiMarketGroupsHistoryDTO;
import com.zhn.evsi.domain.dto.evsi.EvsiMarketGroupsOrdersDTO;
import com.zhn.evsi.domain.dto.evsi.EvsiMarketStatDTO;
import com.zhn.evsi.domain.dto.evsi.character.EvsiCharacterPublicInfoDTO;
import com.zhn.evsi.domain.dto.evsi.market.EvsiMarketOrderDTO;
import com.zhn.evsi.domain.entity.evsi.EvsiInvtypes;
import com.zhn.evsi.domain.entity.evsi.EvsiMarketgroups;
import com.zhn.evsi.domain.vo.EvsiMarketValuationVO;
import com.zhn.evsi.exception.CustomException;
import com.zhn.evsi.interceptor.CharacterInterceptor;
import com.zhn.evsi.mapper.EvsiMarketgroupsMapper;
import com.zhn.evsi.service.IEvsiInvtypesService;
import com.zhn.evsi.service.IEvsiMarketgroupsService;
import com.zhn.evsi.utils.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class EvsiMarketgroupsServiceImpl extends ServiceImpl<EvsiMarketgroupsMapper, EvsiMarketgroups> implements IEvsiMarketgroupsService {

    @Value("${eve.jitaRegionLimit}")
    private String regionLimit;

    @Value("${eve.sellTax}")
    private Double sellTaxValue;

    @Value("${eve.buyTax}")
    private Double buyTaxValue;

    @Resource
    private MarketClient marketClient;

    @Resource
    private ThirdClient thirdClient;

    @Resource
    private TimeUtil timeUtil;

    @Autowired
    private RedisCache redisCache;


    @Autowired
    private IEvsiInvtypesService invtypesService;
    @Autowired
    private CharacterInterceptor characterInterceptor;



    /**
     * 查询我的订单
     * 并查询到我的订单的市场情况
     * */
    @Override
    public List<EvsiMarketOrderDTO> groupsOrders() {
        EvsiCharacterPublicInfoDTO characters = characterInterceptor.getCharacters(null);
        List<EvsiMarketOrderDTO> orders = marketClient.orders(characters.getCharacters());

        if (ObjectUtil.isNotNull(orders)) {
            List<Integer> typeIdList = orders.stream().map(EvsiMarketOrderDTO::getType_id).collect(Collectors.toList());
            Integer[] typeIds = typeIdList.toArray(new Integer[0]);
            List<EvsiMarketStatDTO> marketStatDTOList = this.marketStat(typeIds, regionLimit);

            orders.forEach(type -> {
                String typeName = invtypesService.getOne(new LambdaQueryWrapper<EvsiInvtypes>().eq(EvsiInvtypes::getTypeId, type.getType_id())).getTypeName();
                type.setType_name(typeName);
                marketStatDTOList.forEach(market -> {
                    if (ObjectUtil.equal(type.getType_id(), market.getSell().getForQuery().getTypes().get(0))) {
                        type.setEvsiMarketStatDTO(market);
                    }
                });
            });
        }
        return orders;
    }


    /**
     * 通过id获取当前市场详情
     * */
    @Override
    public List<EvsiMarketStatDTO> marketStat(Integer[] typeId, String regionLimit) {

        // 配置防止科学计数
        NumberFormat instance = NumberFormat.getInstance();
        instance.setGroupingUsed(false);

        List<EvsiMarketStatDTO> evsiMarketStatDTOList = new ArrayList<>();

        String typeIdOnString = ArrayUtil.join(typeId, ",");

        List<JSONObject> marketstat = thirdClient.marketstat(typeIdOnString, regionLimit);
        marketstat.forEach(item -> {
            EvsiMarketStatDTO evsiMarketStatDTO = JSON.toJavaObject(item, EvsiMarketStatDTO.class);

            // 进行数据增加与税率计算
            // 单个税后
            evsiMarketStatDTO.getSell().setMinTax(Double.valueOf(instance.format(evsiMarketStatDTO.getSell().getMin() - evsiMarketStatDTO.getSell().getMin() * sellTaxValue)));
            evsiMarketStatDTO.getBuy().setMaxTax(Double.valueOf(instance.format(evsiMarketStatDTO.getBuy().getMax() - evsiMarketStatDTO.getBuy().getMax() * buyTaxValue)));

            evsiMarketStatDTOList.add(evsiMarketStatDTO);
        });

        return evsiMarketStatDTOList;

    }

    /**
     * 查询我的订单历史
     * */
    @Override
    public List<EvsiMarketGroupsHistoryDTO> groupsHistory(Long characters) {
        List<EvsiMarketGroupsHistoryDTO> evsiMarketGroupsHistoryDTOList = new ArrayList<>();
        List<JSONObject> historyList = new ArrayList<>();
        for (int pageNum=1; pageNum<100; pageNum++) {
            List<JSONObject> history = marketClient.history(characters, pageNum);
            historyList.addAll(history);
            if (history.size() < 1000) {
                break;
            }
        }

        historyList.forEach(v -> {
            EvsiMarketGroupsHistoryDTO evsiMarketGroupsHistoryDTO = JSON.toJavaObject(v, EvsiMarketGroupsHistoryDTO.class);
            evsiMarketGroupsHistoryDTOList.add(evsiMarketGroupsHistoryDTO);
        });

        return evsiMarketGroupsHistoryDTOList;
    }

    /**
     * 通过商品组获取商品具体信息
     * */
    @Override
    public List<EvsiInvtypes> groupsType(Integer marketGroupId) {
        LambdaQueryWrapper<EvsiInvtypes> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EvsiInvtypes::getMarketGroupId, marketGroupId);
        List<EvsiInvtypes> list = invtypesService.list(wrapper);
        return list;
    }

    /**
     * 构造市场商品组树状结构
     * */
    @Override
    public List<EvsiMarketgroups> groupsMenu(Integer state) {
        String menuType = "";

        switch (state) {
            case 0:
                menuType = "market";
                break;
            case 2:
                menuType = "bluePrint";
                break;
            case 4:
                menuType = "ship";
                break;
        }
        List<EvsiMarketgroups> groupsMenu = redisCache.getCacheObject("group:menu:" + menuType + ":");
        if (groupsMenu == null) {
            // 查询出来所有
            List<EvsiMarketgroups> evsiMarketgroupsList = this.list();

            if (state == 0) {
                // 查询出来的父id是空的
                groupsMenu = evsiMarketgroupsList.stream()
                        .filter(groupsMenuParent -> groupsMenuParent.getParentGroupId() == null)
                        .map(menu -> {
                            menu.setChildren(getChildren(menu, evsiMarketgroupsList));
                            return menu;
                        }).collect(Collectors.toList());

            }else {
                groupsMenu = evsiMarketgroupsList.stream()
                        .filter(groupsMenuParent -> Objects.equals(groupsMenuParent.getMarketGroupId(), state))
                        .map(menu -> {
                            menu.setChildren(getChildren(menu, evsiMarketgroupsList));
                            return menu;
                        }).collect(Collectors.toList());
            }

            redisCache.setCacheObject("group:menu:" + menuType + ":", groupsMenu, 5, TimeUnit.DAYS);
        }
        return groupsMenu;
    }

    /**
     * 递归获取商品组信息
     * */
    private List<EvsiMarketgroups> getChildren( EvsiMarketgroups menu, List<EvsiMarketgroups> all) {
        return all.stream().filter(groupsMenu -> Objects.equals(groupsMenu.getParentGroupId(), menu.getMarketGroupId()))
                .map(groupsMenu -> {
            groupsMenu.setChildren(getChildren(groupsMenu, all));
            return groupsMenu;
        }).collect(Collectors.toList());
    }

    /**
     * 估价
     * */
    @Override
    public String valuation(String text) {

        if (StrUtil.isEmpty(text)) {
            throw new CustomException("文本为空！");
        }
        // 文本分割处理
        // 字符串按行分割（正则判断 微软、apple、linux 格式）
        List<String> split = new ArrayList<>();
        if (contains("\r\n", text)) {
            split = StrUtil.split(text, "\r\n");
        }else {
            if (contains("\n", text)) {
                split = StrUtil.split(text, "\n");
            }else if (contains("\r", text)) {
                split = StrUtil.split(text, "\r");
            }else {
                split.add(text);
            }
        }

        // 每行的数据取前面的名字以及后面的数字
        List<EvsiMarketValuationVO> evsiMarketValuationVOList = new ArrayList<>();
        List<EvsiMarketValuationVO> removeType = new ArrayList<>();
        split.forEach(v -> {
            List<String> splitSpace = StrUtil.split(v, " ");
            String splitSpaceStart = null;
            // 判断
            if (splitSpace.size() > 2) {
                for (int i=0; i<splitSpace.size()-1; i++) {
                    if (splitSpaceStart == null) {
                        splitSpaceStart = splitSpace.get(i);
                    }else {
                        splitSpaceStart = splitSpaceStart + " " + splitSpace.get(i);
                    }

                }
            }else {
                splitSpaceStart = splitSpace.get(0);
            }

            EvsiInvtypes invtypes = invtypesService.getOne(new LambdaQueryWrapper<EvsiInvtypes>().eq(EvsiInvtypes::getTypeName, splitSpaceStart));

            if (invtypes != null){
                // id、名称、数量、打包体积、sell最低、sell月中位数、buy最高、buy月中位数
                evsiMarketValuationVOList.add(EvsiMarketValuationVO.builder()
                        .typeId(invtypes.getTypeId())
                        .typeName(invtypes.getTypeName())
                        .quantity(Integer.valueOf(splitSpace.get(splitSpace.size() - 1)))
                        .packagedVolume(invtypes.getPackagedVolume() * splitSpace.size() - 1)
                        .volume(invtypes.getVolume() * splitSpace.size() - 1)
                        .state(0)
                        .build());
            }else {
                removeType.add(EvsiMarketValuationVO.builder()
                        .typeName(splitSpace.get(0))
                        .quantity(splitSpace.size() - 1)
                        .state(1)
                        .build());
                return;
            }
        });

        if (evsiMarketValuationVOList.size() == 0) {
            throw new CustomException("输入的物品名称有错误");
        }

        List<Integer> collect = evsiMarketValuationVOList.stream().map(EvsiMarketValuationVO::getTypeId).collect(Collectors.toList());
        List<List<Integer>> partition;
        List<JSONObject> marketStat = new ArrayList<>();

        partition = ListUtil.partition(collect, 200);

        partition.forEach(v -> {
            String join = CollUtil.join(v, ",");
            List<JSONObject> market = thirdClient.marketstat(join, "10000002");
            marketStat.addAll(market);
        });
        marketStat.forEach(v -> {
            EvsiMarketStatDTO evsiMarketStatDTO = JSON.toJavaObject(v, EvsiMarketStatDTO.class);
            evsiMarketValuationVOList.forEach(k -> {
                if (ObjectUtil.equal(k.getTypeId(), evsiMarketStatDTO.getBuy().getForQuery().getTypes().get(0))) {
                    k.setSellMin(evsiMarketStatDTO.getSell().getMin() * k.getQuantity());
                    k.setSellMedian(evsiMarketStatDTO.getSell().getMedian() * k.getQuantity());
                    k.setSellTax((evsiMarketStatDTO.getSell().getMin() - evsiMarketStatDTO.getSell().getMin() * sellTaxValue) * k.getQuantity());
                    k.setBuyMax(evsiMarketStatDTO.getBuy().getMax() * k.getQuantity());
                    k.setBuyMedian(evsiMarketStatDTO.getBuy().getMedian() * k.getQuantity());
                    k.setBuyTax((evsiMarketStatDTO.getBuy().getMax() - evsiMarketStatDTO.getBuy().getMax() * buyTaxValue) * k.getQuantity());
                }
            });
        });

        // 时间设置

        Map<String, Object> map = new LinkedHashMap<>();// LinkedHashMap存储时顺序固定
        map.put("Sell", evsiMarketValuationVOList.stream().map(EvsiMarketValuationVO::getSellMin).reduce(Double::sum).get());
        map.put("Buy", evsiMarketValuationVOList.stream().map(EvsiMarketValuationVO::getBuyMax).reduce(Double::sum).get());
        map.put("Split", (evsiMarketValuationVOList.stream().map(EvsiMarketValuationVO::getSellMin).reduce(Double::sum).get() + evsiMarketValuationVOList.stream().map(EvsiMarketValuationVO::getBuyMax).reduce(Double::sum).get()) / 2);
        map.put("Volume", evsiMarketValuationVOList.stream().map(EvsiMarketValuationVO::getVolume).reduce(Float::sum).get());
        map.put("PackagedVolume", evsiMarketValuationVOList.stream().map(EvsiMarketValuationVO::getPackagedVolume).reduce(Float::sum).get());
        map.put("createTime", timeUtil.TimeFormatOnSecond());
        evsiMarketValuationVOList.addAll(removeType);
        map.put("dataList", evsiMarketValuationVOList);

        // 生成六位id，通过id保存到redis（2天），并且返回验证参数，用来回调
        String randomString;
        // 防止id相同
        while (true) {
            randomString = RandomUtil.randomString(6);
            Map<String, Object> mapRedis = redisCache.getCacheObject("valuation:" + randomString);
            if (mapRedis == null) {
                break;
            }
        }

        redisCache.setCacheObject("valuation:" + randomString, map, 2, TimeUnit.DAYS);
        return randomString;
    }

    /**
     * 正则表达式包含
     * */
    public static boolean contains(String regex, String source) {
        Pattern pattern = Pattern.compile(regex);
        return pattern.matcher(source).find();
    }

    /**
     * 估价回调
     * */
    @Override
    public Map<String, Object> valuationCallBack(String randomString) {
        return redisCache.getCacheObject("valuation:" + randomString);
    }
}
